﻿using BasicModuleWebApiJWTAuthorization.Module;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;

//using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
using Signalrs.HubModel;
using System.IdentityModel.Tokens.Jwt;


//using Microsoft.IdentityModel.Tokens;
////using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace Signalrs.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class LoginController : ControllerBase
    {
        private readonly IHttpContextAccessor _accessor;
        public IHubContext<ChatRoomHub> hubContext;

        public LoginController(IHubContext<ChatRoomHub> hubContext)
        {
            this.hubContext = hubContext;
            //_accessor = httpContextAccessor;
        }

        [Route("Login")]
        [HttpPost]
        public IActionResult Login(T_User t_User)
        {
            //1.判断用户是否登录
            //if (t_User.Name == "123" && t_User.Password == "123")
            //{
            //ClaimTypes.Name
            Claim[] claims = new Claim[] {
                new Claim (JwtRegisteredClaimNames.Name,t_User.Name),
                //通过将jti设置为一个唯一的值（如UUID），JWT可以被用作一次性令牌。一旦令牌被使用或过期，它就不能再被接受，这减少了重放攻击的风险。
                //在创建JWT时，应使用一种能够生成唯一值的算法（如UUID）来设置jti字段
                //服务器应存储已使用的jti值，并在验证JWT时检查该值是否已被使用
                //结合JWT的过期时间（exp字段）和唯一标识符，可以进一步增强安全性。即使攻击者截获了令牌，它也会在短时间内过期，无法被重放。
                new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString()),
                 new Claim(ClaimTypes.NameIdentifier,t_User.Id.ToString()),  //ClaimTypes.NameIdentifier 通常表示的是“用户唯一标识”，即用户 ID。
                new Claim("Passwd",t_User.Password)
              };
            //string issuer = null, 签发者 。生产token系统
            //string audience = null, 受用者 erp系统
            //IEnumerable<Claim> claims = null,  登录信息
            //DateTime? notBefore = null, 生成token时间
            //DateTime? expires = null,  token过期时间
            //SigningCredentials signingCredentials = null 签名凭证 【签名字符串】防止数据被篡改

            //SecurityKey 密钥
            //密钥：R2XMnd6TQdYRUmR0cCfL9fk651Fb3kDI
            SecurityKey securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("R2XMnd6TQdYRUmR0cCfL9fk651Fb3kDI"));
            //加密算法准备 非对称算法
            //签名凭证
            //SigningCredentials signingCredentials = new SigningCredentials(securityKey,SecurityAlgorithms.Sha256); //非对称算法
            SigningCredentials signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); //对称算法
            JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(
                issuer: "jwt",
                audience: "BasicModuleWebApiJWTAuthorization",
                claims: claims,
                notBefore: DateTime.Now,
                expires: DateTime.Now.AddMinutes(30.0),
                signingCredentials: signingCredentials);
            //创建token 
            JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
            //生成token
            string token = handler.WriteToken(jwtSecurityToken);

            hubContext.Clients.All.SendAsync("ReceivePublicMessage", "欢迎新用户登陆成功", "123").Wait();

            return Ok(token);
            //}
            //return Unauthorized(new { message = "登录失败，用户名或密码错误。" });
        }

        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        [RequestSizeLimit(4004857600)] // 100MB
        [HttpPost("file")]
        public async Task<IActionResult> UploadFile(IFormFile file)
        {
            var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;

            var buffer = new byte[81920]; // 80KB缓冲
            var totalRead = 0L;
            var totalLength = file.Length;

            var savePath = Path.Combine("Uploads", file.FileName);
            Directory.CreateDirectory("Uploads");

            using var stream = new FileStream(savePath, FileMode.Create);
            using var fileStream = file.OpenReadStream();

            int read;
            while ((read = await fileStream.ReadAsync(buffer)) > 0)
            {
                await stream.WriteAsync(buffer.AsMemory(0, read));
                totalRead += read;

                var progress = (int)((double)totalRead / totalLength * 100);
                if (!string.IsNullOrEmpty(userId))
                {
                    await hubContext.Clients.User(userId)
                        .SendAsync("ReceiveProgress", progress);
                }
            }

            return Ok(new { success = true });
        }

        [HttpGet("GetTask")]
        public async Task<string> GetTask()
        {
            Console.WriteLine($"1:{Thread.CurrentThread.ManagedThreadId}");
            Test();
            Console.WriteLine($"2:{Thread.CurrentThread.ManagedThreadId}");
            //Task.CompletedTask;
            return "xxx";
        }

        [HttpGet("Test")]
        public async Task Test()
        {
            Console.WriteLine($"3:{Thread.CurrentThread.ManagedThreadId}");
            await Task.Delay(10000);
            Console.WriteLine($"4:{Thread.CurrentThread.ManagedThreadId}");
        }
    }
}
